use std::collections::HashSet;

pub fn solute() {
    let contents = std::fs::read_to_string("./day03/input.txt").unwrap();
    let mut lines = Vec::new();
    for line in contents.lines() {
        lines.push(line);
    }

    let get_number = |row: usize, col: usize| -> u32 {
        // line[row][col] is a digit
        // Find left
        let line = lines[row].as_bytes();
        let mut begin: usize = col;
        loop {
            if begin == 0 || !(line[begin - 1] as char).is_digit(10) {
                break;
            }
            begin -= 1;
        }

        let mut end: usize = col + 1;
        loop {
            if end >= line.len() || !(line[end] as char).is_digit(10) {
                break;
            }
            end += 1;
        }
        
        (&lines[row][begin..end]).parse().unwrap()
    };

    let get_sround_numbers = |row: usize, col: usize| -> HashSet<u32> {
        let mut result = HashSet::new();

        let col_size = lines.first().unwrap().len();
        let row_size = lines.len();

        if row > 0 && col > 0 && (lines[row-1].as_bytes()[col-1] as char).is_digit(10) {
            result.insert(get_number(row-1, col-1));
        }

        if row > 0 && (lines[row-1].as_bytes()[col] as char).is_digit(10) {
            result.insert(get_number(row-1, col));
        }

        if row > 0 && col < col_size - 1 && (lines[row-1].as_bytes()[col+1] as char).is_digit(10) {
            result.insert(get_number(row-1, col+1));
        }

        ///////////////////////

        if col > 0 && (lines[row].as_bytes()[col-1] as char).is_digit(10) {
            result.insert(get_number(row, col-1));
        }

        if col < col_size - 1 && (lines[row].as_bytes()[col+1] as char).is_digit(10) {
            result.insert(get_number(row, col+1));
        }

        ///////////////////////
        
        if row < row_size - 1 && col > 0 && (lines[row+1].as_bytes()[col-1] as char).is_digit(10) {
            result.insert(get_number(row+1, col-1));
        }

        if row < row_size - 1 && (lines[row+1].as_bytes()[col] as char).is_digit(10) {
            result.insert(get_number(row+1, col));
        }

        if row < row_size - 1 && col < col_size - 1 && (lines[row+1].as_bytes()[col+1] as char).is_digit(10) {
            result.insert(get_number(row+1, col+1));
        }

        result
    };

    let mut sum: u32 = 0;
    for (row, &line) in lines.iter().enumerate() {
        for (col, &byte) in line.as_bytes().iter().enumerate() {
            if byte == b'*' {
                // May be a gear
                let numbers = get_sround_numbers(row, col);
                if numbers.len() != 2 {
                    continue;
                }
                let mut iter = numbers.into_iter();
                let r = iter.next().unwrap();
                let r = r * iter.next().unwrap();
                sum += r;
            }
        }
    }
    println!("{sum}");
}